/******************************************************************************
*	cmList.h	Header file of CM List Module
*
*	coypright (C) 2009 Ding Lixing
*
******************************************************************************/

#ifndef __CMLIST_INC__
#define __CMLIST_INC__

#ifdef __cplusplus
extern "C" {
#endif

typedef struct __cmLISTNODE {
    struct __cmLISTNODE * volatile next;
    struct __cmLISTNODE * volatile prev;
}cmLISTNODE;

typedef struct cmLISTHEAD {
    cmLISTNODE * volatile first;
    cmLISTNODE * volatile last;
}cmLISTHEAD;

#define cmListNodeInit(node)                                                   \
(                                                                              \
    (((cmLISTNODE *)(node))->next = (cmLISTNODE *)0),                          \
    (((cmLISTNODE *)(node))->prev = (cmLISTNODE *)0),                          \
    0                                                                          \
)

#define cmListHeadInit(head)                                                   \
(                                                                              \
    (((cmLISTHEAD *)(head))->first = (cmLISTNODE *)(head)),                    \
    (((cmLISTHEAD *)(head))->last  = (cmLISTNODE *)(head)),                    \
    0                                                                          \
)

#define cmListNodeGetContainer(c, t, n)                                        \
((c *)(((unsigned long)(n)) - ((unsigned long)(&(((c *)0)->t)))))

#define cmListNodeGetNext(node)                                                \
((cmLISTNODE *)(((cmLISTNODE *)(node))->next))

#define cmListNodeAdd(pos, node)                                               \
do{                                                                            \
    ((cmLISTNODE *)(node))->next = ((cmLISTNODE *)(pos))->next;                \
    ((cmLISTNODE *)(node))->prev = ((cmLISTNODE *)(pos));                      \
    ((cmLISTNODE *)(pos))->next->prev = ((cmLISTNODE *)(node));                \
    ((cmLISTNODE *)(pos))->next = ((cmLISTNODE *)(node));                      \
}while(0)

#define cmListNodeInsert(pos, node)                                            \
do{                                                                            \
    ((cmLISTNODE *)(node))->next = ((cmLISTNODE *)(pos));                      \
    ((cmLISTNODE *)(node))->prev = ((cmLISTNODE *)(pos))->prev;                \
    ((cmLISTNODE *)(pos))->prev->next = ((cmLISTNODE *)(node));                \
    ((cmLISTNODE *)(pos))->prev = ((cmLISTNODE *)(node));                      \
}while(0)

#define cmListNodeDel(node)                                                    \
do{                                                                            \
    ((cmLISTNODE *)(node))->prev->next = ((cmLISTNODE *)(node))->next;         \
    ((cmLISTNODE *)(node))->next->prev = ((cmLISTNODE *)(node))->prev;         \
}while(0)


#define cmListGetFirst(head) (((cmLISTHEAD *)(head))->first)
#define cmListGetLast(head)  (((cmLISTHEAD *)(head))->last)
#define cmListGetEnd(head)   ((cmLISTNODE *)(head))

#define cmListAdd(head, node)                                                  \
do{                                                                            \
    cmLISTNODE *prev = cmListGetLast(head);                                    \
    cmListNodeAdd(prev, node);                                                 \
}while(0)


#define cmListShift(head)                                                      \
do{                                                                            \
    cmLISTNODE *node = cmListGetFirst(head);                                   \
    cmListNodeDel(node);                                                       \
    cmListAdd(head, node);                                                     \
}while(0)

#define cmListIsEmpty(head)                                                    \
(((cmLISTHEAD *)(head))->first == ((cmLISTNODE *)(head)))


#ifdef __cplusplus
}
#endif

#endif /* __CMLIST_INC__ */

